<template>
  <!-- alt键 + 点击 跳转到文档页面 -->
  <el-card shadow="hover">
    <template #header>
      <el-button type="primary" :icon="Plus" @click="showDialog({tmName: '', logoUrl: ''})">添加</el-button>
    </template>

    <el-table :data="list" border v-loading="loading">
      <el-table-column label="序号" type="index" width="80" align="center"/>
      <el-table-column label="品牌名称" prop="tmName"/>
      <el-table-column label="品牌LOGO">
        <template v-slot="{row, $index}"> <!-- row: 当前行数据对象 -->
          <el-image :src="row.logoUrl" style="width:100px;height: 60px;"></el-image>
        </template>
      </el-table-column>

      <el-table-column label="操作">
        <template v-slot="{row, $index}">
          <el-button type="warning" size="small" :icon="Edit" @click="showDialog(row)"></el-button>
          <el-button type="danger" size="small" :icon="Delete" @click="remove(row)"></el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 当分页器内部的当前页码和每页数量发生改变时, 会自动更新父组件中的对应数据
      当current-change和size-change事件发生时, 数据已经变了
    -->
    <el-pagination
      style="margin-top: 20px;"
      v-model:current-page="currentPage"
      v-model:page-size="pageSize"
      :total="total"
      :page-sizes="[3, 6, 9]"
      layout="prev, pager, next, jumper, ->, sizes, total"
      @current-change="getList"
      @size-change="getList"
    />

    <el-dialog v-model="isShowDialog" :title="trademarkForm.id ? '修改品牌' : '添加品牌'">
      <el-form :model="trademarkForm" label-width="140px" :rules="rules" ref="formRef">
        <el-form-item label="品牌名称" prop="tmName">
          <el-input v-model="trademarkForm.tmName" autocomplete="off" placeholder="请输入品牌名称"/>
        </el-form-item>
        <el-form-item label="品牌LOGO" prop="logoUrl">
          <!-- 
            action: 处理图片上传请求的url
                  不能直接写目标地址  => 跨域了
                  必须写一个带代理前缀路径的路径
            show-file-list: false  单个图片
           -->
          <el-upload
            class="avatar-uploader"
            :action="`${BASE_UPLOAD}/admin/product/fileUpload`"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="trademarkForm.logoUrl" :src="trademarkForm.logoUrl" class="avatar" />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>

            <template #tip>
            <div class="el-upload__tip">只能上传jpg/png文件，且不超过50kb</div>
          </template>

          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="isShowDialog = false">取消</el-button>
          <el-button type="primary" @click="confirm">确定</el-button>
        </span>
      </template>
    </el-dialog>

  </el-card>
</template>

<script lang="ts">
export default {
  name: 'Trademark',
}
</script>

<script lang="ts" setup>
import type { TrademarksModel, TrademarkModel } from '@/api/product/model/trademarkModel';
import { getTrademarkPageListApi, removeTrademarkApi, saveTrademarkApi, saveTrademarkApi2, updateTrademarkApi } from '@/api/product/trademark';
import { Delete, Edit, Plus } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox, type FormInstance, type UploadProps } from 'element-plus';
import { ref, onMounted, reactive, nextTick } from 'vue';


/* 删除品牌 start */
const remove = (row: TrademarkModel) => {
  ElMessageBox.confirm(
    `确定删除${row.tmName}吗?`,
    '提示',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
    .then(async () => { // 点击确定 
      // 请求删除
      await removeTrademarkApi(row.id as number)
      // 成功后提示, 重新显示列表
      ElMessage.success('删除成功!')
      //  如果当页就一条数据, 请求显示上一页
      if (list.value.length===1) {
        // 将当前页码减一
        currentPage.value -= 1
      }
      getList()
    })
    .catch((error) => { // 点击取消 或前面请求失败了 都会调用
      // console.log(error)
      if (error==='cancel') { // 点击取消时error为'cancel'
        ElMessage({
          type: 'info',
          message: '取消删除',
        })
      }
    })
}
/* 删除品牌 end */

/* 添加与更新 start */

const BASE_UPLOAD = import.meta.env.VITE_BASE_URL
const isShowDialog = ref(false) // 标识对话框是否显示
// 收集品牌表单数据
const trademarkForm = reactive<TrademarkModel>({
  tmName: '',
  logoUrl: ''
})

// 显示添加/更新的dialog
const showDialog = (trademark: TrademarkModel) => {
  // 显示dialog
  isShowDialog.value = true
  // 如果trademark有值, 更新trademarkForm显示到表单中
  // if (trademark) {  // 点击添加时, 传入一个空的trademark对象
    trademarkForm.id = trademark.id
    trademarkForm.tmName = trademark.tmName
    trademarkForm.logoUrl = trademark.logoUrl
  // }

  //  手动清除校验错误信息: 
  // 内部的校验操作是异步执行, 我们清除操作发生校验之前
  // formRef.value?.clearValidate()

  // 必须延迟执行校验操作, 让它在自动校验之后清除

  // 使用定时器(宏任务)  可以的
  // setTimeout(() => {
  //   formRef.value?.clearValidate()
  // }, 0);

  // 使用nextTick(微任务)  有问题
  // 原因: 校验的异步任务在当前nextTick微任务之后才执行
  // nextTick(() => {
  //   formRef.value?.clearValidate()
  // })
  
  // 使用2个嵌套的nextTick  可以
  nextTick(() => {
    nextTick(() => {
      formRef.value?.clearValidate()
    })
  })

  // 原因: 内部的异步校验是在点击回调执行完后, 启动微任务去校验的
  // 如果就一层nextTick, 回调是在校验之前执行的  => 没有效果
  // 如果是二层nextTick, 内层的回调就是在校验之后才执行  => 有效果
  // 如果直接使用定时器, 它使用的是宏任务, 在校验之后执行 => 肯定有效果
}

/* 
在上传请求成功后调用
将上传成功的图片保存到trademarkForm.logoUrl
response: 响应体对象 {data: 图片url}
*/
const handleAvatarSuccess: UploadProps['onSuccess'] = (
  response,
  uploadFile
) => {
  console.log(response)
  // trademarkForm.logoUrl = URL.createObjectURL(uploadFile.raw!)  // 产生的url是一个临时的, 后面不能再用
  trademarkForm.logoUrl = response.data

  // 清除logo的错误提示信息
  formRef.value?.clearValidate(['logoUrl'])
}

/* 
在准备发送上传请求前调用, 如果返回值是false, 就不发请求
如果图片类型不是jpg/png, 或者大小超过50kb, 就返回false, 并提示
*/
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (rawFile.type !== 'image/jpeg' && rawFile.type !== 'image/png') {
    ElMessage.error('图片必须是jpg或png')
    return false
  } else if (rawFile.size / 1024  > 50) {
    ElMessage.error('图片不能超过50KB!')
    return false
  }
  return true
}


const formRef = ref<FormInstance>()
// 表单校验规则列表
const rules = reactive({
  tmName: [
    {required: true, message: '品牌名称是必须的', trigger: 'change'}, // 必须的
    // 使用内置校验规则实现
    // {min: 3, max: 6, message: '品牌名称长必须在3到6位'/* , trigger: 'change' */}, // 长度必须是3到6位
    // 使用自定义校验来实现
    {validator: validateTmName, trigger: 'change'}
  ],
  logoUrl: [
    {required: true, message: '品牌LOGO是必须的'}
  ]
})

function validateTmName (rule: any, value: any, callback: any) {
  if (value.length<3 || value.length>6) {
  	// 如果校验不通过, 调用callback指定包含错误信息的error, 或者直接指定错误信息
    // callback(new Error('品牌名称长必须在3到6位'))
    callback('品牌名称长必须在3到6位!!!!')
  } else {
  	// 校验通过时, 直接调用callback, 不传递任何参数
    callback()
  }
}

/* 
确认请求添加或更新
*/
const confirm = () => {
  // 对表单进行统一校验
  formRef.value?.validate(async (valid) => { // valid校验是否通过
    // 校验成功后
    if (valid) {
      // 发添加/更新请求, 看trademarkForm.id是否有值
      if (trademarkForm.id) {
        await updateTrademarkApi(trademarkForm)
      } else {
        // saveTrademarkApi(trademarkForm.tmName, trademarkForm.logoUrl)
        await saveTrademarkApi2(trademarkForm)
      }
      // 成功之后, 隐藏dialog, 重新获取列表显示, 提示添加或更新成功
      isShowDialog.value = false
      getList()
      ElMessage.success(`${trademarkForm.id ? '更新' : '添加'}成功!`)
    }
  })

  
}

/* 添加与更新 end */

/* 分页列表 start */
const list = ref<TrademarksModel>([]) // 当前页的列表
const currentPage = ref(1) // 当前页码
const pageSize = ref(3) // 每页数量
const total = ref(0) // 总数量
const loading = ref(false) // 是否显示loading

//要提前定义一个获取分页列表的函数
const getList = async () => {
  // 显示loading
  loading.value = true

  // 发请求
  const result = await getTrademarkPageListApi(currentPage.value, pageSize.value)

  // 请求成功后更新数据
  list.value = result.records
  total.value = result.total
  // 隐藏loading
  loading.value = false
}

// 初始化获取分页列表显示
onMounted(() => {
  getList()
})

/* 分页列表 end */

// 通过defineExpose来向外暴露函数
defineExpose({
  getList2: getList
})
  
</script>

<style scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>